﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.IO;

namespace dahtd4ever
{
    public class Enemy
    {
        private ContentManager e_content;

        Game1 game;

        Texture2D enemyTexture;
        Animation enemyAnim;
        Texture2D hp_low;
        Texture2D hp_middle;
        Texture2D hp_high;
        TileMap map;
        Vector2 actualTile;
        Vector2 position = new Vector2 (0,200);
            public Vector2 getPosition() { return this.position; }
        Vector2 moveDirection;

        Rectangle boundarie;
            public Rectangle getBoundarie(){return this.boundarie;}

        float moveSpeed = 1;
        float moveDistance = 0;
        bool changeDirection = false;
        bool up_last = false;
        bool down_last = false;
        bool right_last = false;

        String texturePath;
        //bool spawn;

        float hpInPercent;
        float hp;
            public float getHp() { return this.hp; }
            public void setHp(float hp) { this.hp = hp; }
        float hpMax;

        float resourcesByDeath;
            public float getResourcesByDeath() { return this.resourcesByDeath; }
        float lifelossByWalktrough;
            public float getLifelossByWalktrough() { return this.lifelossByWalktrough; }    

        float armor;
        int type;

        public List<DOT> dots;

        int spawntime = 2;
            public int getSpawntime() { return this.spawntime; }
        bool go = false;
            public bool ifGo() { return this.go; }
            public void Go() { this.go = true; }
        bool active = true;
            public bool Active() { return this.active; }
            public void Inactive() { this.active = false; }

        // Konstruktor
        public Enemy(TileMap map, int type, Game1 game)
        {
            this.game = game;

            this.map = map;
            // hier spawn noch festzulegen
            boundarie = new Rectangle((int)position.X, (int)position.Y, map.getTileWidth(), map.getTileHeight());

            // GegnerFolder
            String enemyPath = "Enemies/0" + type + ".enemy";
            if (type > 9) { enemyPath = "Enemies/" + type + ".enemy"; }

            // GEGNER EINLESEN
            System.IO.StreamReader file;
            String currentDirectory = GetProjectPath();
            // Enemy-Datei öffnen
            file = new System.IO.StreamReader(Path.Combine(currentDirectory, enemyPath));

            // Typ
            file.ReadLine();
            this.type = Convert.ToInt32(file.ReadLine());
            // Textur
            file.ReadLine();
            this.texturePath = Convert.ToString(file.ReadLine());
            // Leben
            file.ReadLine();
            this.hpMax = this.hp = Convert.ToInt32(file.ReadLine());
            // Rüstung
            file.ReadLine();
            this.armor = Convert.ToInt32(file.ReadLine());
            // Speed
            file.ReadLine();
            this.moveSpeed = (float)Convert.ToInt32(file.ReadLine()) / 100;
            // ABzug bei durchkommen
            file.ReadLine();
            this.lifelossByWalktrough = Convert.ToInt32(file.ReadLine());
            // Geld bei Ableben
            file.ReadLine();
            this.resourcesByDeath = Convert.ToInt32(file.ReadLine());

            file.Close();

        }

        public bool Initialize(ContentManager content)
        {
            this.e_content = content;
            this.dots = new List<DOT>();
            return true;
        }

        public void LoadContent()
        {
            enemyTexture = e_content.Load<Texture2D>(texturePath);
            enemyAnim = new Animation();
            enemyAnim.Initialize(enemyTexture, new Vector2(this.boundarie.X + this.boundarie.Width / 2, this.boundarie.Y + this.boundarie.Height / 2), 100, 100, 2, 300, Color.White, 0.5f, true);

            hp_high = e_content.Load<Texture2D>("Graphics/hpHigh");
            hp_middle = e_content.Load<Texture2D>("Graphics/hpMiddle");
            hp_low = e_content.Load<Texture2D>("Graphics/hpLow");
        }

        public void Update(GameTime gameTime)
        {
            actualTile = map.PosToTile(new Vector2(this.boundarie.X, this.boundarie.Y));//setActualTile(map);
            move(map);
            boundarie.X = (int)position.X;
            boundarie.Y = (int)position.Y;

            enemyAnim.Position.X = this.boundarie.X + this.boundarie.Width / 2;
            enemyAnim.Position.Y = this.boundarie.Y + this.boundarie.Height / 2;
            enemyAnim.Update(gameTime);

            // alle Dots ticken lassen und evtl entfernen
            for (int i = 0; i < dots.Count; i++)
            {

                dots[i].Update(this, game, gameTime);
                if (!dots[i].active)
                {
                    dots.RemoveAt(i);
                }

            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            //spriteBatch.Draw(enemyTexture, new Rectangle((int)position.X, (int)position.Y, map.getTileWidth(), map.getTileHeight()), Color.White);
            enemyAnim.Draw(spriteBatch);

            hpInPercent = hp / hpMax * 100;
            if (hpInPercent > 50) { spriteBatch.Draw(hp_high, new Rectangle((int)position.X, (int)position.Y, map.getTileWidth() * (int)hpInPercent / 100, map.getTileHeight()), Color.White); }
            if (hpInPercent <= 50 & hpInPercent > 20) { spriteBatch.Draw(hp_middle, new Rectangle((int)position.X, (int)position.Y, map.getTileWidth() * (int)hpInPercent / 100, map.getTileHeight()), Color.White); }
            if (hpInPercent <= 20 & hpInPercent > 0) { spriteBatch.Draw(hp_low, new Rectangle((int)position.X, (int)position.Y, map.getTileWidth() * (int)hpInPercent / 100, map.getTileHeight()), Color.White); }
            if (dots.Count > 0)
            {
                spriteBatch.DrawString(game.font2, Convert.ToString(dots.Count), new Vector2(this.boundarie.X, this.boundarie.Y), Color.White);
            }
        }

        // Tile zum Spawnen ermitteln
        private void setSpawn(TileMap map)
        {
            int mapHoehe = map.GetHeight();
            int tileHoehe = map.getTileHeight();
            Tile tile = new Tile();
            Vector2 spawnPosition = new Vector2();
            
            // X-Koordinaten setzen
            spawnPosition.X = 0;
            
            // jedes Tile in letzter Kachelreihe auf "Weg" checken
            for (int i = 0; i < mapHoehe; i++)
            {
                tile = map.GetTile(0, i);
                if (tile.weg == true)
                {
                    // wenn gefunden: Y-Koordinaten setzen
                   spawnPosition.Y = i * tileHoehe; // Kachelposition * Kachelhoehe
                }
            }

            this.position = spawnPosition;
        }

        // Bewegung des Gegners
        private void move(TileMap map)
        {
            if (moveDistance <= 0) { changeDirection = true; }

            //  abcheken der anliegenden Kacheln für neue Richtung
            if (changeDirection)
            {
                // Mögliche Richtungen
                bool right = checkNextTileRight();
                bool down = checkNextTileLower();
                bool up = checkNextTileUpper();

                if (right) { GoRight(); moveDistance = map.getTileWidth(); }
                if (up & !right & !down_last) { GoUp(); moveDistance = map.getTileHeight(); }
                if (down & !right & !up_last) { GoDown(); moveDistance = map.getTileHeight(); }

                changeDirection = false;
            }

            // solange nicht anderes gesagt in bestimmte Richtung laufen
            if (!changeDirection)
            {
                position.X += moveDirection.X;
                position.Y += moveDirection.Y;
                moveDistance -= moveSpeed;
            }
        }

            // Kachelabfrage: Links von aktueller Position
            private bool checkNextTileRight()
            {
                int x = (int) this.actualTile.X + 1;
                    if (x < 0) { x = 0; }
                    if (x >= map.GetWidth()) { x = map.GetWidth() - 1; }
                int y = (int) this.actualTile.Y;
                    if (y < 0) { y = 0; }
                    if (y >= map.GetHeight()) { x = map.GetHeight() - 1; }
                if (map.GetTile(x,y).weg == true) { return true; }
                else {return false;}
            }

            // Kachelabfrage: Oben von aktueller Position
            private bool checkNextTileUpper()
            {
                int x = (int)this.actualTile.X;
                    if (x < 0) { x = 0; }
                    if (x >= map.GetWidth()) { x = map.GetWidth() - 1; }
                int y = (int)this.actualTile.Y - 1;
                    if (y < 0) { y = 0; }
                    if (y >= map.GetHeight()) { x = map.GetHeight() - 1; }
                if (map.GetTile(x, y).weg == true) { return true; }
                else { return false; }
            }

            // Kachelabfrage: Unten von aktueller Position
            private bool checkNextTileLower()
            {
                int x = (int)this.actualTile.X;
                    if (x < 0) { x = 0; }
                    if (x >= map.GetWidth()) { x = map.GetWidth() - 1; }
                int y = (int)this.actualTile.Y + 1;
                    if (y < 0) { y = 0; }
                    if (y >= map.GetHeight()) { x = map.GetHeight() - 1; }
                if (map.GetTile(x, y).weg == true) { return true; }
                else { return false; }
            }

            // Bewegungsrichtungen
            private void GoUp()
            {
                moveDirection.X = 0;
                moveDirection.Y = moveSpeed * -1;
                up_last = true; right_last = false; down_last = false;
            }

            private void GoDown()
            {
                moveDirection.X = 0;
                moveDirection.Y = moveSpeed;
                down_last = true; up_last = false; right_last = false;
            }

            private void GoRight()
            {
                moveDirection.X = moveSpeed;
                moveDirection.Y = 0;
                right_last = true; up_last = false; down_last = false;
            }

        //Dateipfad finden
        internal static string GetProjectPath()
        {
            // Ergebnis: Debug- oder Release-Ordner im Projektordner.
            string projectPath = Environment.CurrentDirectory;
            // Mit jedem Durchlauf geht es im Verzeichnisbaum eine Stufe höher.
            for (int i = 0; i <= 4; i++)
            {
                projectPath = System.IO.Path.GetDirectoryName(projectPath);
            }
            return projectPath + @"\";
        }
    
    }
}
